/*
 * CrystalMonsterMonitor
 * 
 * Deployed on a "minimal Arduino"
 *
 * 2009, Tod E. Kurt, http://todbot.com/blog/
 */
 
const int ledPin          = 13;       // 
const int inputPin        = 4;        // button input
const int monsterResetPin = 9;        // reset signal to monster

boolean monsterOn = true;
boolean monsterAlive = true;
boolean buttonPushed = false;
boolean wasButtonPushed = false;
unsigned long lastAliveMillis;
unsigned long lastButtonMillis;
int noAnswerMillis = 5000;

void setup() {
  Serial.begin(19200);
  
  pinMode(ledPin, OUTPUT);      // declare LED as output
  pinMode(inputPin, INPUT);     // declare pushbutton as input
  pinMode(monsterResetPin, OUTPUT); // 
  digitalWrite(monsterResetPin, HIGH);
  digitalWrite(inputPin, HIGH); // turn on internal pullup
  
  Serial.println("CrystalMonsterMonitor ready");
}

void loop() {

  if( Serial.available() ) {       // monster is still alive
    monsterAlive = true;
    lastAliveMillis = millis();
    digitalWrite(ledPin,HIGH);     // it's alive!
    Serial.flush();                // clean it out, we don't need to read it
    Serial.println("alive!");
  }
  else {  // if no serial available, monster may be dead
    if( (millis() - lastAliveMillis) > noAnswerMillis )
      monsterAlive = false;
  }
  
  boolean buttonPushed = (digitalRead(inputPin)==LOW) ? true : false;  // read button
  if( buttonPushed ) {
      digitalWrite(ledPin,HIGH);
      Serial.println("boom");                           // tap to go boom
      delay(500);
      digitalWrite(ledPin,LOW);
  }
  /*
  if( buttonPushed ) {
    if( lastButtonMillis == 0 ) {
      lastButtonMillis = millis();
    }
    if( (millis() - lastButtonMillis) > 1000 ) {
      digitalWrite(ledPin,HIGH);
      Serial.println( (monsterAlive) ? "off" : "on" );
      monsterOn = (monsterAlive) ? false : true;     // oh we've turned it off
      delay(250);
      digitalWrite(ledPin,LOW);
    }
  }
  else {
    if( lastButtonMillis > 0 ) {
      digitalWrite(ledPin,HIGH);
      Serial.println("boom");                           // tap to go boom
      delay(250);
      digitalWrite(ledPin,LOW);
    }
    lastButtonMillis = 0;
  }
  */

  if( monsterOn && !monsterAlive ) {
     resetMonster();
  }
  
  delay(50);
  digitalWrite(ledPin,LOW);

}

//
void resetMonster() {
  Serial.println("dead");
  
  digitalWrite(monsterResetPin, LOW);
  delay(500);
  digitalWrite(monsterResetPin, HIGH);
  
  for( int i=0; i<=10; i++ ) {
    digitalWrite(ledPin, HIGH); // turn LED ON
    delay(50);
    digitalWrite(ledPin, LOW);
    delay(50);
  }
  monsterAlive = true;  // give it a chance to be alive for a while
  lastAliveMillis = millis();
}


/*
 *  note this only works for ATmega168 or better
 *


#include <avr/sleep.h>
#include <avr/wdt.h>

volatile boolean hit_wdt = false;

void loop() {
//...
  if (wdt_hit==1) { // wait for timed out watchdog / flag is set when a watchdog timeout occurs
    wdt_hit = 0;       // reset flag
    Serial.println("watchdog!");
  }
//...
  system_sleep();
}

//****************************************************************  

// set system into the sleep state 
// system wakes up when wtchdog is timed out
void system_sleep() {
  set_sleep_mode(SLEEP_MODE_PWR_DOWN); 
  sleep_enable();
  sleep_mode();                        // System sleeps here
  sleep_disable();                     // System continues here when watchdog times out 
}

//****************************************************************
// 0=16ms, 1=32ms,2=64ms,3=128ms,4=250ms,5=500ms
// 6=1 sec,7=2 sec, 8=4 sec, 9= 8sec
void setup_watchdog(int ii) {

  byte bb;
  int ww;
  if (ii > 9 ) ii=9;
  bb=ii & 7;
  if (ii > 7) bb|= (1<<5);
  bb|= (1<<WDCE);
  ww=bb;
  Serial.println(ww);

  MCUSR &= ~(1<<WDRF);
  // start timed sequence
  WDTCSR |= (1<<WDCE) | (1<<WDE);
  // set new watchdog timeout value
  WDTCSR = bb;
  WDTCSR |= _BV(WDIE);
}

// Watchdog Interrupt Service / is executed when  watchdog timed out
ISR(WDT_vect) {
  wdt_hit = true;  // set global flag
}

*/
